package agrep4me;

import java.util.Enumeration;

class Table1 extends Table {
	protected States w1;
	protected States w2;

	protected void initialize(Auto a, int nerrs, States ex) {
		fstate = a.fstate;

		// alpha = new States[NCHARS];
		// for (int c = 0; c < NCHARS; c++) {
		// alpha[c] = ex.empty();
		// }
		w1 = ex.empty();
		w2 = ex.empty();
	}

	Table1(Auto a, int nerrs, States ex) {
		super(ex);
		// System.err.println("Niveau a") ;
		initialize(a, nerrs, ex);
		// System.err.println("fstate=" + fstate) ;
		for (int state = 0; state < fstate; state++) {
			for (Transition p = a.trans[state]; p != null; p = p.next) {
				// alpha[p.label].add(state);
				alphaGet(p.label).add(state);
			}
			if (a.dot[state]) {
				Enumeration enume = alphaElements();
				while (enume.hasMoreElements()) {
					States st = (States) enume.nextElement();
					st.add(state);
				}
				// for (int c = 0; c < size; c++)
				// alpha[c].add(state);
			}
		}
	}

	States initial() {
		States r = w1.empty();
		r.add(0);
		return r;
	}

	States initialErr(States prev) {
		States r = prev.copy();
		r.shift();
		r.or(prev);
		return r;
	}

	void step(States s, char c) {
		// System.out.println((int)c);
		// s.and(alpha[c]);
		s.and(alphaGet(c));
		s.shift();
		s.add(0);
	}

	// pless = previous value with -1 error
	// less = current value with -1 error
	void stepErr(States s, char c, States pless, States less) {
		w1.assign(s);
		w2.assign(pless);
		// Normal
		step(s, c);
		// Introduce errors
		pless.or(less);
		pless.shift();
		pless.or(w2);
		// Combine
		s.or(pless);
		pless.assign(w1);
	}

	private States[] s;
	private States[] s_init;
	private int slen;
	private States w;

	private boolean matchLine(String line) {
		for (int k = 0; k < slen; k++)
			s[k].assign(s_init[k]);

		if (s[slen - 1].mem(fstate))
			return true;

		int len = line.length();
		for (int i = 0; i < len; i++) {
			char c = line.charAt(i);
			w.assign(s[0]);
			step(s[0], c);
			// System.err.println(w + " - " + c + " -> " + s[0]) ;
			for (int k = 1; k < slen; k++) {
				stepErr(s[k], c, w, s[k - 1]);
			}
			if (s[slen - 1].mem(fstate)) {
				// System.out.println("<<<" + c + ">>>");
				return true;
			}
		}
		return false;
	}

	void match(Fichier f, int nerrs) {
		slen = nerrs + 1;
		w = w1.empty();
		s = new States[slen];
		s_init = new States[slen];

		s[0] = w1.empty();
		s_init[0] = initial();
		for (int k = 1; k < slen; k++) {
			s[k] = w1.empty();
			s_init[k] = initialErr(s_init[k - 1]);
		}

		String line;
		while ((line = f.nextString()) != null) {
			if (matchLine(line))
				System.out.println(line);
		}
	}
}
